package sk.tuke.constraintbuilder.views;

import java.io.File;
import java.util.Iterator;

import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.wb.swt.SWTResourceManager;

import sk.tuke.constraintbuilder.handler.CallEditor;
import sk.tuke.constraintbuilder.handler.CloseEditor;
import sk.tuke.constraintbuilder.handler.ListRefresh;
import sk.tuke.constraintbuilder.model.Constraint;
import sk.tuke.constraintbuilder.model.Model;
import sk.tuke.constraintbuilder.model.Ruleset;
import sk.tuke.constraintbuilder.model.Template;
import sk.tuke.constraintbuilder.utils.MyImages;
import sk.tuke.constraintbuilder.utils.MyUtils;
import sk.tuke.constraintbuilder.utils.XMLUtils;

public class ConstraintExplorerView extends ViewPart {
	
	//Viewers
	private ListViewer rulesetViewer;
	private ListViewer constraintViewer;
	private ListViewer templateViewer;
	
	//Forms Sections
	private Section rulesetSection;
	private Section constraintSection;
	private Section templateSection;

	public static final String ID = "sk.tuke.constraintbuilder.explorerView";
	private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());

	public ConstraintExplorerView() {
		setPartName("Constraint Explorer");
	}

	/**
	 * Create contents of the view part.
	 * @param parent
	 */
	@Override
	public void createPartControl(Composite parent) {
		Composite container = new Composite(parent, SWT.NONE);
		
		Form viewForm = formToolkit.createForm(container);
		viewForm.getHead().setFont(SWTResourceManager.getFont("Segoe UI", 10, SWT.BOLD));
		viewForm.setBounds(0, 0, 296, 469);
		formToolkit.paintBordersFor(viewForm);
		viewForm.setText("Annotations Constraint Explorer");
		viewForm.getBody().setLayout(new GridLayout(1, false));
		
		// RULESET SECTION ///////////////////////////////////////////////////////////////////////////////////////////
		rulesetSection = formToolkit.createSection(viewForm.getBody(), Section.TWISTIE | Section.TITLE_BAR);
		rulesetSection.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		formToolkit.paintBordersFor(rulesetSection);
		rulesetSection.setText("Rulesets");
		rulesetSection.setExpanded(true);
		
		Composite rulesetPanel = formToolkit.createComposite(rulesetSection, SWT.NONE);
		formToolkit.paintBordersFor(rulesetPanel);
		rulesetSection.setClient(rulesetPanel);
		rulesetPanel.setLayout(new GridLayout(2, false));
		
		rulesetViewer = new ListViewer(rulesetPanel, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
		rulesetViewer.setContentProvider(ArrayContentProvider.getInstance());
		rulesetViewer.setLabelProvider(new LabelProvider() {
			@Override
			public String getText(Object element) {
				Ruleset ruleset = (Ruleset) element;
				return String.valueOf(ruleset.getName());
			};
		});
		rulesetViewer.setInput(Model.getModel().getRulesets());
		List list = rulesetViewer.getList();
		list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		
		ToolBar rulesetToolbar = new ToolBar(rulesetPanel, SWT.FLAT | SWT.RIGHT | SWT.VERTICAL);
		rulesetToolbar.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, false, false, 1, 1));
		formToolkit.adapt(rulesetToolbar);
		formToolkit.paintBordersFor(rulesetToolbar);
		
		ToolItem newButton = new ToolItem(rulesetToolbar, SWT.NONE);
		newButton.setText("New");
		newButton.setImage(MyImages.ADD);
		newButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		MyUtils.executeParametrizedCommand(CallEditor.COMMAND, CallEditor.PARAMETER, CallEditor.NEW_RULESET, getSite());
	    	}
		});
		
		ToolItem editButton = new ToolItem(rulesetToolbar, SWT.NONE);
		editButton.setText("Edit");
		editButton.setImage(MyImages.EDIT);
		editButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		String ID = MyUtils.getFirstIDFromSelection(rulesetViewer.getSelection());
	    		MyUtils.executeParametrizedCommand(CallEditor.COMMAND, CallEditor.PARAMETER, ID, getSite());
	    	}
		});
		
		ToolItem removeButton = new ToolItem(rulesetToolbar, SWT.NONE);
		removeButton.setText("Remove");
		removeButton.setImage(MyImages.REMOVE);
		removeButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		getSite().setSelectionProvider(rulesetViewer);
	    		ISelection selection = rulesetViewer.getSelection();
        		if (selection != null && selection instanceof IStructuredSelection) {
        			Iterator<?> iterator = ((IStructuredSelection) selection).iterator();
        			boolean answer = MessageDialog.openQuestion(PlatformUI.getWorkbench().getModalDialogShellProvider().getShell(),
    						"Confirm delete", "Do you really want to delete "+((IStructuredSelection) selection).size()+" rulesets?");
        			if(answer){
        				MyUtils.executeCommand(CloseEditor.COMMAND, getSite());
	        			while(iterator.hasNext()){
	        				Object obj = iterator.next();
	            			if (obj != null) {
	            				Ruleset ruleset = (Ruleset) obj;
	            				Model.getModel().delete(ruleset);
	            			}
	        			}
                    	MyUtils.executeCommand(ListRefresh.COMMAND, getSite());
        			}
        		}
	    	}
		});
		
		ToolItem fromFileButton = new ToolItem(rulesetToolbar, SWT.NONE);
		fromFileButton.setText("From File");
		fromFileButton.setImage(MyImages.OPEN);
		fromFileButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		FileDialog dlg = new FileDialog(getSite().getShell(), SWT.MULTI);
	    		dlg.setFilterExtensions(new String[] { "*.xml" });
	    	    if (dlg.open() != null) {
	    	    	String[] names = dlg.getFileNames();
	    	    	String path = dlg.getFilterPath();
	    	        for (int i = 0, n = names.length; i < n; i++) {
	    	        	Path fullPath = new Path(path+"\\"+names[i]);
	    	        	File file = fullPath.toFile();
	    	        	if(file != null){
	    	        		Ruleset ruleset = XMLUtils.xmlToRuleset(file);
	    	        		if(ruleset != null){
			    	        	Model.getModel().addRuleset(ruleset);
			    	        	Model.getModel().save(ruleset);
			    				MyUtils.executeCommand(ListRefresh.COMMAND, getSite());
	    	        		}
	    	        	}
	    	        }
	    	    }
	    	}	
		});
		
		//CONSTRAINT SECTION /////////////////////////////////////////////////////////////////
		constraintSection = formToolkit.createSection(viewForm.getBody(), Section.TWISTIE | Section.TITLE_BAR);
		constraintSection.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		formToolkit.paintBordersFor(constraintSection);
		constraintSection.setText("Constraints");
		constraintSection.setExpanded(true);
		
		Composite constraintPanel = formToolkit.createComposite(constraintSection, SWT.NONE);
		formToolkit.paintBordersFor(constraintPanel);
		constraintSection.setClient(constraintPanel);
		constraintPanel.setLayout(new GridLayout(2, false));
		
		constraintViewer = new ListViewer(constraintPanel, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
		constraintViewer.setContentProvider(ArrayContentProvider.getInstance());
		constraintViewer.setLabelProvider(new LabelProvider() {
			@Override
			public String getText(Object element) {
				Constraint constraint = (Constraint) element;
				return String.valueOf(constraint.getName());
			};
		});
		constraintViewer.setInput(Model.getModel().getConstraints());
		List list_1 = constraintViewer.getList();
		list_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
		
		ToolBar constraintToolbar = new ToolBar(constraintPanel, SWT.FLAT | SWT.RIGHT | SWT.VERTICAL);
		formToolkit.adapt(constraintToolbar);
		formToolkit.paintBordersFor(constraintToolbar);
		
		newButton = new ToolItem(constraintToolbar, SWT.NONE);
		newButton.setText("New");
		newButton.setImage(MyImages.ADD);
		newButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		MyUtils.executeParametrizedCommand(CallEditor.COMMAND, CallEditor.PARAMETER, CallEditor.NEW_CONSTRAINT, getSite());
	    	}
		});
		
		editButton = new ToolItem(constraintToolbar, SWT.NONE);
		editButton.setText("Edit");
		editButton.setImage(MyImages.EDIT);
		editButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		String ID = MyUtils.getFirstIDFromSelection(constraintViewer.getSelection());
	    		MyUtils.executeParametrizedCommand(CallEditor.COMMAND, CallEditor.PARAMETER, ID, getSite());
	    	}
		});
		
		removeButton = new ToolItem(constraintToolbar, SWT.NONE);
		removeButton.setText("Remove");
		removeButton.setImage(MyImages.REMOVE);
		removeButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		getSite().setSelectionProvider(constraintViewer);
	    		ISelection selection = constraintViewer.getSelection();
	    		if (selection != null && selection instanceof IStructuredSelection) {
        			Iterator<?> iterator = ((IStructuredSelection) selection).iterator();
        			boolean answer = MessageDialog.openQuestion(PlatformUI.getWorkbench().getModalDialogShellProvider().getShell(),
    						"Confirm delete", "Do you really want to delete "+((IStructuredSelection) selection).size()+" constraints?");
        			if(answer){
        				MyUtils.executeCommand(CloseEditor.COMMAND, getSite());
	        			while(iterator.hasNext()){
	        				Object obj = iterator.next();
	            			if (obj != null) {
	            				Constraint constraint = (Constraint) obj;
	            				Model.getModel().delete(constraint);
	            			}
	        			}
                    	MyUtils.executeCommand(ListRefresh.COMMAND, getSite());
        			}
        		}
	    	}
		});
		
		fromFileButton = new ToolItem(constraintToolbar, SWT.NONE);
		fromFileButton.setText("From File");
		fromFileButton.setImage(MyImages.OPEN);
		fromFileButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		FileDialog dlg = new FileDialog(getSite().getShell(), SWT.MULTI);
	    		dlg.setFilterExtensions(new String[] { "*.xml" });
	    	    if (dlg.open() != null) {
	    	    	String[] names = dlg.getFileNames();
	    	    	String path = dlg.getFilterPath();
	    	        for (int i = 0, n = names.length; i < n; i++) {
	    	        	Path fullPath = new Path(path+"\\"+names[i]);
	    	        	File file = fullPath.toFile();
	    	        	if(file!=null){
	    	        		sk.tuke.constraintbuilder.model.Constraint constraint = XMLUtils.xmlToConstraint(file);
	    	        		if(constraint != null){
	    	        			Model.getModel().addConstraint(constraint);
	    	        			Model.getModel().save(constraint);
			    				MyUtils.executeCommand(ListRefresh.COMMAND, getSite());
	    	        		}
	    	        	}

	    	        }
	    	    }
	    	}	
		});
		
		//TEMPLATE SECTION
		templateSection = formToolkit.createSection(viewForm.getBody(), Section.TWISTIE | Section.TITLE_BAR);
		templateSection.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		formToolkit.paintBordersFor(templateSection);
		templateSection.setText("Templates");
		templateSection.setExpanded(true);
		
		Composite templatePanel = formToolkit.createComposite(templateSection, SWT.NONE);
		formToolkit.paintBordersFor(templatePanel);
		templateSection.setClient(templatePanel);
		templatePanel.setLayout(new GridLayout(2, false));
		
		templateViewer = new ListViewer(templatePanel, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
		templateViewer.setContentProvider(ArrayContentProvider.getInstance());
		templateViewer.setLabelProvider(new LabelProvider() {
			@Override
			public String getText(Object element) {
				Template template = (Template) element;
				return String.valueOf(template.getName());
			};
		});
		templateViewer.setInput(Model.getModel().getTemplates());
		List list_2 = templateViewer.getList();
		list_2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
		
		ToolBar templateToolbar = new ToolBar(templatePanel, SWT.FLAT | SWT.RIGHT | SWT.VERTICAL);
		formToolkit.adapt(templateToolbar);
		formToolkit.paintBordersFor(templateToolbar);
		
		newButton = new ToolItem(templateToolbar, SWT.NONE);
		newButton.setText("New");
		newButton.setImage(MyImages.ADD);
		newButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		MyUtils.executeParametrizedCommand(CallEditor.COMMAND, CallEditor.PARAMETER, CallEditor.NEW_TEMPLATE, getSite());
	    	}
		});
		
		editButton = new ToolItem(templateToolbar, SWT.NONE);
		editButton.setText("Edit");
		editButton.setImage(MyImages.EDIT);
		editButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		String ID = MyUtils.getFirstIDFromSelection(templateViewer.getSelection());
	    		MyUtils.executeParametrizedCommand(CallEditor.COMMAND, CallEditor.PARAMETER, ID, getSite());
	    	}
		});
		
		removeButton = new ToolItem(templateToolbar, SWT.NONE);
		removeButton.setText("Remove");
		removeButton.setImage(MyImages.REMOVE);
		removeButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		getSite().setSelectionProvider(templateViewer);
	    		ISelection selection = templateViewer.getSelection();
	    		if (selection != null && selection instanceof IStructuredSelection) {
        			Iterator<?> iterator = ((IStructuredSelection) selection).iterator();
        			boolean answer = MessageDialog.openQuestion(PlatformUI.getWorkbench().getModalDialogShellProvider().getShell(),
    						"Confirm delete", "Do you really want to delete "+((IStructuredSelection) selection).size()+" templates?");
        			if(answer){
        				MyUtils.executeCommand(CloseEditor.COMMAND, getSite());
	        			while(iterator.hasNext()){
	        				Object obj = iterator.next();
	            			if (obj != null) {
	            				Template template = (Template) obj;
	            				Model.getModel().delete(template);
	            			}
	        			}
                    	MyUtils.executeCommand(ListRefresh.COMMAND, getSite());
        			}
        		}
	    	}
		});
		
		fromFileButton = new ToolItem(templateToolbar, SWT.NONE);
		fromFileButton.setText("From File");
		fromFileButton.setImage(MyImages.OPEN);
		fromFileButton.addSelectionListener(new SelectionAdapter() {
	    	public void widgetSelected(SelectionEvent e) {
	    		FileDialog dlg = new FileDialog(getSite().getShell(), SWT.MULTI);
	    		dlg.setFilterExtensions(new String[] { "*.xml" });
	    	    if (dlg.open() != null) {
	    	    	String[] names = dlg.getFileNames();
	    	    	String path = dlg.getFilterPath();
	    	        for (int i = 0, n = names.length; i < n; i++) {
	    	        	Path fullPath = new Path(path+"\\"+names[i]);
	    	        	File file = fullPath.toFile();
	    	        	if(file!=null){
	    	        		Template template = XMLUtils.xmlToTemplate(file);
	    	        		if(template != null){
			    	        	Model.getModel().addTemplate(template);
			    	        	Model.getModel().save(template);
			    				MyUtils.executeCommand(ListRefresh.COMMAND, getSite());
	    	        		}
	    	        	}
	    	        }
	    	    }
	    	}	
		});

		hookDoubleClickCommand();
	}

	private void hookDoubleClickCommand() {
		constraintViewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
	    		String ID = MyUtils.getFirstIDFromSelection(constraintViewer.getSelection());
	    		MyUtils.executeParametrizedCommand(CallEditor.COMMAND, CallEditor.PARAMETER, ID, getSite());
			}
		});
		templateViewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
	    		String ID = MyUtils.getFirstIDFromSelection(templateViewer.getSelection());
	    		MyUtils.executeParametrizedCommand(CallEditor.COMMAND, CallEditor.PARAMETER, ID, getSite());
			}
		});
		rulesetViewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
	    		String ID = MyUtils.getFirstIDFromSelection(rulesetViewer.getSelection());
	    		MyUtils.executeParametrizedCommand(CallEditor.COMMAND, CallEditor.PARAMETER, ID, getSite());
			}
		});
	}

	public void refresh() {
		constraintViewer.refresh();
		templateViewer.refresh();
		rulesetViewer.refresh();
		
		List rulesetList = rulesetViewer.getList();
		List constraintList = constraintViewer.getList();
		List templateList = templateViewer.getList();
		
		Point size = rulesetList.computeSize(SWT.DEFAULT, SWT.DEFAULT);
		rulesetList.setBounds(0, 0, size.x, size.y);
		formToolkit.adapt(rulesetList, true, true);
		rulesetList.getParent().layout();
		rulesetList.getParent().getParent().layout();
		
		size = constraintList.computeSize(SWT.DEFAULT, SWT.DEFAULT);
		constraintList.setBounds(0, 0, size.x, size.y);
		formToolkit.adapt(constraintList, true, true);
		constraintList.getParent().layout();
		constraintList.getParent().getParent().layout();

		
		size = templateList.computeSize(SWT.DEFAULT, SWT.DEFAULT);
		templateList.setBounds(0, 0, size.x, size.y);
		formToolkit.adapt(templateList, true, true);
		templateList.getParent().layout();
		templateList.getParent().getParent().layout();
		templateList.getParent().getParent().getParent().layout();
	}

	@Override
	public void setFocus() {
		// TODO Auto-generated method stub
		
	}
}
